#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <vector>
#define MAX_SIZE  100
#define MIN(a, b) ((a) < (b) ? (a) : (b))

namespace MyNamespace {
    template <typename T, typename U>
    class MyClass {
      public:
        MyClass () :
            value (T ()), name ("Unnamed") {}

        MyClass (T val, std::string n) :
            value (val), name (n) {}

        T getValue () const { return value; }

        void setValue (T val) { value = val; }

        std::string getName () const { return name; }

        void setName (const std::string & n) { name = n; }

        void printInfo () const {
            std::cout << "Name: " << name << ", Value: " << value << std::endl;
        }

        U calculate (U a, U b) { return a + b; }

        friend std::ostream & operator<< (std::ostream & os, const MyClass & obj) {
            os << "MyClass [name=" << obj.name << ", value=" << obj.value << "]";
            return os;
        }

      private:
        T           value;
        std::string name;
    };

    template <typename T>
    void processVector (std::vector<T> & vec) {
        for (auto & elem : vec) {
            std::cout << elem << " ";
        }
        std::cout << std::endl;
    }

    class Base {
      public:
        virtual void foo () = 0;
    };

    class Derived : public Base {
      public:
        void foo () override { std::cout << "Derived foo" << std::endl; }
    };

    void bar (Base * b) { b->foo (); }

    class ComplexNumber {
      public:
        ComplexNumber (double r, double i) :
            real (r), imag (i) {}

        ComplexNumber operator+ (const ComplexNumber & other) const {
            return ComplexNumber (real + other.real, imag + other.imag);
        }

        void display () const {
            std::cout << "Real: " << real << ", Imag: " << imag << std::endl;
        }

      private:
        double real;
        double imag;
    };

    template <typename T>
    T add (T a, T b) { return a + b; }
    enum class Colors {
        RED,
        GREEN,
        BLUE
    };

    std::map<std::string, int> createMap () {
        std::map<std::string, int> m;
        m["one"]   = 1;
        m["two"]   = 2;
        m["three"] = 3;
        return m;
    }

    void pointerExample () {
        int * p = new int (42);
        std::cout << "Pointer value: " << *p << std::endl;
        delete p;
    }

    int * returnPointer () {
        int * ptr = new int (100);
        return ptr;
    }

    void referencesExample () {
        int   a   = 10;
        int & ref = a;
        std::cout << "Reference value: " << ref << std::endl;
    }

    void conditionalExample (int x) {
        if (x > 10) {
            std::cout << "x is greater than 10" << std::endl;
        } else if (x == 10) {
            std::cout << "x is equal to 10" << std::endl;
        } else {
            std::cout << "x is less than 10" << std::endl;
        }
    }

    void loopExamples () {
        for (int i = 0; i < 10; ++i) {
            std::cout << "For loop: " << i << std::endl;
        }
        int j = 0;
        while (j < 5) {
            std::cout << "While loop: " << j << std::endl;
            ++j;
        }
        do {
            std::cout << "Do-while loop: " << j << std::endl;
            ++j;
        } while (j < 10);
    }

    void switchExample (Colors color) {
        switch (color) {
            case Colors::RED:
                std::cout << "Color is Red" << std::endl;
                break;
            case Colors::GREEN:
                std::cout << "Color is Green" << std::endl;
                break;
            case Colors::BLUE:
                std::cout << "Color is Blue" << std::endl;
                break;
            default:
                std::cout << "Unknown color" << std::endl;
                break;
        }
    }

    std::string ternaryExample (int y) {
        return y > 0 ? "Positive" : "Non-positive";
    }

    void exceptionExample () {
        try {
            throw std::runtime_error ("An error occurred");
        } catch (const std::runtime_error & e) {
            std::cerr << "Caught an exception: " << e.what () << std::endl;
        } catch (...) {
            std::cerr << "Caught an unknown exception" << std::endl;
        }
    }

    class ResourceHandler {
      public:
        ResourceHandler () {
            resource = new int (42);
            std::cout << "Resource acquired" << std::endl;
        }

        ~ResourceHandler () {
            delete resource;
            std::cout << "Resource released" << std::endl;
        }

      private:
        int * resource;
    };

    void functionPointerExample () {
        void (*func) (int) = [] (int x) {
            std::cout << "Lambda with " << x << std::endl;
        };
        func (5);
    }

    void initializerListExample (std::initializer_list<int> list) {
        for (auto elem : list) {
            std::cout << elem << " ";
        }
        std::cout << std::endl;
    }
}  // namespace MyNamespace

void ABC (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j,
          int k, int l, int m, int n, int o, int p, int q, int r, int s, int t,
          int u, int v, int w, int x, int y, int z) {}

struct test {
    int          A;
    int          B;
    const char * C;
} demo[] = {
        {56, 23, "hello"},
        {-1, 93'463, "world"},
        {7, 5, "!!"}};

int    a            = 1;
int    somelongname = 2;
double c            = 3;
int    d            = 3;
/* A comment. */
double e            = 4;
// a                &= 2;
// bbb               = 2;
unsigned i;
int &    r = a;
int *    p;
int (*f) ();

// a   >>= 2;
// bbb   = 2;
// a     = 2;
// bbb >>= 2;
int main () {
    //   switch (1) {
    //   case log::info:
    //     return "info:";
    //   case log::warning:
    //     return "warning:";
    //   default:
    //     return "";
    //   }
    0b001'0010'1010'1001;
    0x1'93'21'90'23'89'03'12;
    7'189'024'792'138'901'238;
    using namespace MyNamespace;
    MyClass<int, double> obj (42, "Test");
    obj.printInfo ();
    std::vector<int> vec = {1, 2, 3, 4, 5};
    processVector (vec);
    Derived d;
    bar (&d);
    ComplexNumber c1 (1.0, 2.0);
    ComplexNumber c2 (2.0, 3.0);
    ComplexNumber c3 = c1 + c2;
    c3.display ();
    std::cout << "Add: " << add (10, 20) << std::endl;
    auto map = createMap ();
    for (const auto & pair : map) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }
    pointerExample ();
    int * ptr = returnPointer ();
    std::cout << "Returned pointer: " << *ptr << std::endl;
    delete ptr;
    referencesExample ();
    conditionalExample (10);
    loopExamples ();
    switchExample (Colors::GREEN);
    std::cout << "Ternary: " << ternaryExample (5) << std::endl;
    exceptionExample ();
    { ResourceHandler handler; }
    functionPointerExample ();


    initializerListExample ({1, 2, 3, 4, 5});
    return 0;
}

extern "C" {

void A ();
}
